import { Injectable, NotFoundException } from '@nestjs/common';
import { InjectModel } from '@nestjs/mongoose';
import { Comment, CommentStatus } from '~/shared/mongodb/schema/comment.schema';
import { MongodbService } from '~/shared/mongodb/mongodb.service';
import { paginate, Pagination, paginateAggregate } from '~/helper/paginate';
import { FilterQuery, isValidObjectId, Types } from 'mongoose';
import { BusinessException } from '../../../common/exceptions/business.exception';
import { ErrorEnum } from '../../../constants/error-code.constant';
import {
  CreateCommentDto,
  QueryCommentDto,
  UpdateCommentDto,
} from './comment.dto';

@Injectable()
export class CommentService {
  constructor(private readonly mongodbService: MongodbService) {}

  /**
   * 创建新评论
   */
  async create(createCommentDto: CreateCommentDto): Promise<Comment> {
    if (!isValidObjectId(createCommentDto.productId)) {
      throw new BusinessException(ErrorEnum.INVALID_ID_FORMAT);
    }
    // 验证商品是否存在
    const productExists = await this.mongodbService.ProductModel.exists({
      _id: new Types.ObjectId(createCommentDto.productId),
    });

    if (!productExists) {
      throw new BusinessException(ErrorEnum.PRODUCT_NOT_EXIST);
    }

    // 创建评论，状态默认为待审核
    const createdComment = new this.mongodbService.CommentModel({
      ...createCommentDto,
      productId: new Types.ObjectId(createCommentDto.productId),
    });

    return createdComment.save();
  }

  /**
   * 分页查询评论列表
   */
  async findAll(queryDto: QueryCommentDto): Promise<Pagination<Comment>> {
    // 构建查询条件
    const filter: FilterQuery<Comment> = {};

    // 按商品筛选
    if (queryDto.productId) {
      filter.productId = new Types.ObjectId(queryDto.productId);
    }

    // 按状态筛选
    if (queryDto.status) {
      filter.status = queryDto.status;
    }

    // 按用户名模糊查询
    if (queryDto.userName) {
      filter.userName = { $regex: queryDto.userName, $options: 'i' };
    }

    // 执行分页查询
    return paginate(
      this.mongodbService.CommentModel,
      { page: queryDto.page, pageSize: queryDto.pageSize },
      filter,
      {
        sort: { commentTime: -1 }, // 按评论时间降序排列
        projection: { __v: 0 }, // 排除__v字段
      },
    );
  }

  /**
   * 查询单个评论详情
   */
  async findOne(id: string): Promise<Comment> {
    const comment = await this.mongodbService.CommentModel.findById(id).exec();

    if (!comment) {
      throw new NotFoundException(`评论 ID ${id} 不存在`);
    }

    return comment;
  }

  /**
   * 更新评论（主要用于审核）
   */
  async update(
    id: string,
    updateCommentDto: UpdateCommentDto,
  ): Promise<Comment> {
    // 如果更新了商品ID，验证商品是否存在
    if (updateCommentDto.productId) {
      const productExists = await this.mongodbService.ProductModel.exists({
        _id: new Types.ObjectId(updateCommentDto.productId),
      });

      if (!productExists) {
        throw new BusinessException(ErrorEnum.PRODUCT_NOT_EXIST);
      }

      // 转换为ObjectId
      updateCommentDto.productId = new Types.ObjectId(
        updateCommentDto.productId,
      ) as any;
    }

    const updatedComment =
      await this.mongodbService.CommentModel.findByIdAndUpdate(
        id,
        updateCommentDto,
        {
          new: true,
          runValidators: true,
        },
      ).exec();

    if (!updatedComment) {
      throw new NotFoundException(`评论 ID ${id} 不存在`);
    }

    return updatedComment;
  }

  /**
   * 删除评论
   */
  async remove(id: string): Promise<void> {
    const result = await this.mongodbService.CommentModel.deleteOne({
      _id: id,
    }).exec();

    if (result.deletedCount === 0) {
      throw new NotFoundException(`评论 ID ${id} 不存在`);
    }
  }

  /**
   * 批量审核评论
   */
  async batchApprove(
    ids: string[],
    status: CommentStatus,
  ): Promise<{ success: boolean; count: number }> {
    if (!ids || ids.length === 0) {
      throw new BusinessException(ErrorEnum.IDS_IS_EMPTY);
    }

    // 验证ID格式
    ids.forEach(id => {
      if (!Types.ObjectId.isValid(id)) {
        throw new BusinessException(ErrorEnum.INVALID_ID_FORMAT);
      }
    });

    const result = await this.mongodbService.CommentModel.updateMany(
      { _id: { $in: ids.map(id => new Types.ObjectId(id)) } },
      { status },
    ).exec();

    return {
      success: true,
      count: result.modifiedCount,
    };
  }
}
